// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_COLUMN_NAME_PARSER_HPP_
#define _XBASE_COLUMN_NAME_PARSER_HPP_

#include <string>
#include <algorithm>

namespace xbase
{
	// 实现方式为不保存字符串，只解析给定字符串内容！
	//
	// 如果字符串中没有冒号，则会被当作是列族名
	class column_name_parser
	{
	public:
		column_name_parser()
			: m_string_begin(NULL)
			, m_string_end(NULL)
			, m_size(0)
			, m_colon(NULL)
			, m_contain_regex(false)
			, m_any_column(false)
			, m_any_qualifier(false) {}

		column_name_parser(const column_name_parser &other)
			: m_string_begin(other.m_string_begin)
			, m_string_end(other.m_string_end)
			, m_size(other.m_size)
			, m_colon(other.m_colon)
			, m_contain_regex(other.m_contain_regex)
			, m_any_column(other.m_any_column)
			, m_any_qualifier(other.m_any_qualifier) {}

		template<typename string_type> // string_type::data(), string_type::size()
		explicit
		column_name_parser(const string_type &column)
			: m_string_begin(column.data())
			, m_string_end(column.data() + column.size())
			, m_size(column.size())
			, m_colon(column.data() + column.size()) // set to be m_string_end
			, m_contain_regex(false)
			, m_any_column(false)
			, m_any_qualifier(false) {
			parse();
		}

		column_name_parser(const char *column, std::size_t size)
			: m_string_begin(column)
			, m_string_end(column + size)
			, m_size(size)
			, m_colon(column + size) // set to be m_string_end
			, m_contain_regex(false)
			, m_any_column(false)
			, m_any_qualifier(false) {
			parse();
		}

		inline
		column_name_parser &operator=(const column_name_parser &other);

		bool match(const column_name_parser &other) const;

		template<typename string_type>
		inline
		bool match(const string_type &column) const {
			return match(column.data(), column.size());
		}

		bool match(const char *column, std::size_t size) const;

		bool has_regex() const {
			return m_contain_regex;
		}

		bool has_colon() const {
			return ((m_colon != NULL) &&
				(m_colon != m_string_end));
		}

		bool has_qualifier_name() const {
			return ((m_colon + 1) < m_string_end);
		}
		
		// 注意：要求any_column any_qualifier不会同时成立
		bool is_any_column() const {
			return m_any_column;
		}

		bool is_any_qualifier() const {
			return m_any_qualifier;
		}

		std::string column_name() const {
			return std::string(m_string_begin, m_string_end);
		}

		std::string family_name() const {
			return std::string(m_string_begin, m_colon);
		}

		std::string qualifier_name() const {
			if(m_colon != m_string_end)
			{
				return std::string(m_colon + 1, m_string_end); // skip ':'
			}
			else
			{
				return std::string();
			}
		}

		template<typename string_type>
		inline
		int family_name_cmp(const string_type &family_name) const {
			return family_name_cmp(family_name.data(), family_name.size());
		}

		inline
		int family_name_cmp(const char *family_name, std::size_t family_size) const {
			const size_t size = m_colon - m_string_begin;
			return name_cmp(m_string_begin, size,
					family_name, family_size);
		}

		template<typename string_type>
		inline
		int qualifier_name_cmp(const string_type &qualifier_name) const {
			return qualifier_name_cmp(qualifier_name.data(), qualifier_name.size());
		}

		inline
		int qualifier_name_cmp(const char *qualifier_name, std::size_t qualifier_size) const {
			const size_t size = (m_string_end == m_colon
					     ? 0 : m_string_end - m_colon - 1);
			return name_cmp(m_colon + 1, size,
					qualifier_name, qualifier_size);
		}

	protected:
		void parse();

		static
		int name_cmp(const char *name_a, std::size_t size_a,
			     const char *name_b, std::size_t size_b);

	private:
		static const char s_colon_char;
		static const char s_star_char;

		const char * m_string_begin;
		const char * m_string_end;
		size_t m_size;
		const char * m_colon; // == m_string_end, or pointer to s_colon_char
		bool m_contain_regex;

		// 注意：要求any_column any_qualifier不会同时成立，否则可能影响到其它代码
		bool m_any_column; // "*"
		//size_t m_colon_pos;
		bool m_any_qualifier; // "family:*"
	};

	column_name_parser &column_name_parser::operator=(const column_name_parser &other) {
		if(&other != this)
		{
			m_string_begin = other.m_string_begin;
			m_string_end = other.m_string_end;
			m_size = other.m_size;
			m_colon = other.m_colon;
			m_contain_regex = other.m_contain_regex;
			m_any_column = other.m_any_column;
			m_any_qualifier = other.m_any_qualifier;
		}
		return *this;
	}

} // namespace xbase

#endif	// _XBASE_COLUMN_NAME_PARSER_HPP_
